package managers.dateManager.endFrozen.durationChange;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.tbjd.client.beans.Task;
import org.tbjd.client.constants.NotificationsConstants;
import org.tbjd.client.exceptions.TaskManagerException;
import org.tbjd.client.managers.TaskManager;
import org.tbjd.client.states.StateEndFrozenASAP;

import factories.TaskFactory;

/**
 * <p>
 * Test TaskManager's methods
 * </p>
 * <p>
 * <b>Case</b>
 * </p>
 * <p>
 * Task with predecessors
 * </p>
 * <p>
 * <b>Action</b>
 * </p>
 * <p>
 * Change duration of the task "task"
 * </p>
 * <p>
 * <b>Expected</b>
 * <ul>
 * <li>update BeginDate</li>
 * <li>ChainingMode of "task" switch to manual</li>
 * </ul>
 * </p>
 * 
 * @author Michael Martin
 * @author Antonio Carrozzini
 * @version 1.0
 */
public class EndFrozen_DurationChange_Predecessors_Basic extends TestCase {

	/*
	 * Task		Begins 		Ends 		Successor 	ChainingMode	duration + 24 hours
	 * p1		15.6.2009 	17.6.2009 	task		ASAP 			15.6.2009 - 17.6.2009
	 * p2		18.6.2009 	21.6.2009 	task		ASAP 			18.6.2009 - 21.6.2009
	 * task 	22.6.2009 	23.6.2009 	-			ASAP 			21.6.2009 - 23.6.2009
	 */

	private Task task = null;
	private Map<Integer, Object> map = null;
	private Logger log = Logger.getLogger("console");
	private DateFormat df = DateFormat.getInstance();
	private TaskManager dateManager = new TaskManager();

	protected void setUp() throws Exception {
		df = new SimpleDateFormat("dd.MM.yyyy");

		Task p1 = TaskFactory.getInstance();
		p1.setName("p1");
		p1.setBeginDate(df.parse("15.6.2009"));
		p1.setEndDate(df.parse("17.6.2009"));
		p1.setDuration(48f);

		Task p2 = TaskFactory.getInstance();
		p2.setName("p2");
		p2.setBeginDate(df.parse("18.6.2009"));
		p2.setEndDate(df.parse("21.6.2009"));
		p2.setDuration(72f);

		this.task = TaskFactory.getInstance();
		this.task.setName("task");
		this.task.setBeginDate(df.parse("22.6.2009"));
		this.task.setEndDate(df.parse("23.6.2009"));
		this.task.setDuration(24f);
		this.task.setState(new StateEndFrozenASAP(task.getState().getDurationModeState()));

		p1.addSuccessor(this.task);
		p2.addSuccessor(this.task);

		super.setUp();
	}

	public void testReturnedBeanListNotNull() {
		System.out.println("");
		log.debug(" === testReturnedBeanListNotNull");

		float newDuration = 48f;
		log.debug("new duration = " + newDuration);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, newDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call TaskManager...");
		try {
			assertNotNull("Updated bean list isn't null", dateManager.manageDates(map));

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

	}

	public void testListSize() {
		System.out.println("");
		log.debug(" === testListSize");

		float newDuration = 48f;
		log.debug("new duration = " + newDuration);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, newDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}
		assertEquals("Updated bean list size = 1", 1, updatedBeans.size());

	}

	public void testInstanceEquality() {
		System.out.println("");
		log.debug(" === testInstanceEquality");

		float newDuration = 48f;
		log.debug("new duration = " + newDuration);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, newDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals("Task given and received are equals", this.task, updatedBeans.get(0));

	}

	public void testDurations() {
		System.out.println("");
		log.debug(" === testDurations");

		float originalDuration = task.getDuration();
		float newDuration = 48f;

		log.debug("original duration = " + originalDuration);
		log.debug("new Duration = " + newDuration);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, newDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertEquals("Assert Duration has been udated with new Duration", newDuration, updatedBeans.get(0).getDuration());

	}

	public void testDates() {
		System.out.println("");
		log.debug(" === testDates");

		Date originalEndDate = task.getEndDate();
		float newDuration = 48f;

		log.debug("original EndDate = " + originalEndDate);
		log.debug("new Duration = " + newDuration);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, newDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		try {
			assertEquals(df.parseObject("21.6.2009"), updatedBeans.get(0).getBeginDate());
			assertEquals(df.format(originalEndDate), df.format(updatedBeans.get(0).getEndDate()));

		} catch (ParseException e) {
			fail(e.getMessage());

		}

	}

	public void testChainingModes() {
		System.out.println("");
		log.debug(" === testChainingModes");

		Date originalBeginDate = task.getBeginDate();
		float newDuration = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("new Duration = " + newDuration);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, newDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		log.debug("compute with new Duration = " + newDuration + "...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		assertFalse(updatedBeans.get(0).getState().isASAPChainingMode());

	}

	public void testRevertDurations() {
		System.out.println("");
		log.debug(" === testRevertDurations");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalDuration = task.getDuration();
		float newDuration = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new Duration = " + newDuration);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, newDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original Duration...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, originalDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved Duration = " + updatedBeans.get(0).getDuration() + " & original Duration = " + originalDuration);
		assertEquals("Assert Duration reverted to original", originalDuration, updatedBeans.get(0).getDuration());

	}

	public void testRevertDates() {
		System.out.println("");
		log.debug(" === testRevertDates");

		Date originalBeginDate = task.getBeginDate();
		Date originalEndDate = task.getEndDate();
		float originalDuration = task.getDuration();
		float newDuration = 48f;

		log.debug("original BeginDate = " + originalBeginDate);
		log.debug("original EndDate = " + originalEndDate);
		log.debug("original duration = " + originalDuration);
		log.debug("new Duration = " + newDuration);

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, newDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		try {
			dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("call dateManager with original Duration...");
		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.DATEMANAGER_ACTION_duration, originalDuration);
		this.map.put(NotificationsConstants.DATEMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.DATEMANAGER_SENDER, null);

		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (TaskManagerException e) {
			fail(e.getMessage());

		}

		log.debug("retrieved BeginDate = " + updatedBeans.get(0).getBeginDate() + " & original BeginDate = " + originalBeginDate);
		assertEquals(originalBeginDate, updatedBeans.get(0).getBeginDate());
		assertEquals(originalEndDate, updatedBeans.get(0).getEndDate());

	}
}